import path from 'path';
import fs from 'fs';
import chalk from 'chalk';

const toBase64 = function (PngObject) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    PngObject.pack();
    PngObject.on('data', chunk => {
      chunks.push(chunk);
    });
    PngObject.on('end', () => {
      resolve(
        `data:image/png;base64,${Buffer.concat(chunks).toString('base64')}`
      );
    });
    PngObject.on('error', err => {
      reject(err);
    });
  });
};

const generateSvgTmp = function ({ width, height, href }) {
  return `<?xml version="1.0" encoding="UTF-8"?>
  <!-- generated by lst -->
  <svg version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    viewBox="0 0 ${width} ${height}"
    enable-background="new 0 0 ${width} ${height}"
    xml:space="preserve"
  >
  <image xlink:href="${href}" width="${width}" height="${height}"/>
  </svg>`;
};

const generateSvg = function ({ PngObject, path }) {
  return toBase64(PngObject).then(baseb4 => {
    const svgTmp = generateSvgTmp({
      width: PngObject.width,
      height: PngObject.height,
      href: baseb4
    });
    const name = `${path}.svg`;
    fs.writeFileSync(name, svgTmp);
    return Promise.resolve(name);
  });
};

const generatorPng = function ({ PngObject, path }) {
  return new Promise((resolve, reject) => {
    const name = `${path}.png`;
    PngObject.pack()
      .pipe(fs.createWriteStream(name))
      .on('finish', () => {
        resolve(name);
      })
      .on('error', err => {
        reject(err);
      });
  });
};
function iterationNode(node, handler) {
  function _iterationNode(node, parent) {
    handler(node, parent);
    node.children &&
      node.children.forEach(item => {
        _iterationNode(item, node);
      });
  }
  _iterationNode(node, null);
  return node;
}

function addPath(node) {
  return iterationNode(node, (node, parent) => {
    node.path = parent ? parent.path + node.name + '/' : '';
  });
}

function getImageObjectList(docTree) {
  const docExport = docTree.export();
  addPath(docExport);
  let res = [];
  function cond(item) {
    return /\.(jpe?g|png|text)/i.test(item.name);
  }
  function search(node) {
    if (cond(node)) {
      res.push({
        name: node.name,
        path: node.path
      });
    }
    node.children &&
      node.children.forEach(item => {
        search(item);
      });
  }
  search(docExport, null);
  return res;
}

export default function generatorImage(options) {
  let { docTree, outPath, imgType } = options;
  const imageObjList = getImageObjectList(docTree);
  outPath = path.join(outPath, 'image');
  let handler = imgType === 'png' ? generatorPng : generateSvg;
  let handlers = imageObjList.map(item => {
    const PngObject = docTree.childrenAtPath(item.path)[0].layer.image.toPng();
    item.name = item.name.replace(/\.(jpe?g|png|text|)|(@.*$)/gi, '');
    if (!fs.existsSync(outPath)) fs.mkdirSync(outPath);
    return handler({
      PngObject,
      path: path.join(outPath, item.name)
    });
  });
  Promise.all(handlers)
    .then(res => {
      console.log(chalk.green('图片生成成功，列表：'));
      console.log(res);
    })
    .catch(err => {
      console.log(chalk.red('图片生成失败'));
      console.error(err);
    });
}
